import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';

import { In, Like, Repository } from 'typeorm';

import { BusinessException } from '~/common/exceptions/biz.exception';
import { ErrorEnum } from '~/constants/error-code.constant';
import { paginate } from '~/helper/paginate';
import { Pagination } from '~/helper/paginate/pagination';
import { DictTypeEntity } from '~/modules/system/dict-type/dict-type.entity';

import { DictTypeDto, DictTypeQueryDto } from './dict-type.dto';
import { DictItemService } from '~/modules/system/dict-item/dict-item.service';
import { DictItemEntity } from '../dict-item/dict-item.entity';

@Injectable()
export class DictTypeService {
  constructor(
    @InjectRepository(DictTypeEntity)
    private dictTypeRepository: Repository<DictTypeEntity>,
    private dictItemService: DictItemService
  ) {}

  /**
   * 罗列所有配置
   */
  async page({
    page,
    pageSize,
    name,
    code,
  }: DictTypeQueryDto): Promise<Pagination<DictTypeEntity>> {
    const queryBuilder = this.dictTypeRepository.createQueryBuilder('dict_type').where({
      ...(name && { name: Like(`%${name}%`) }),
      ...(code && { code: Like(`%${code}%`) }),
    });

    return paginate(queryBuilder, { page, pageSize });
  }

  /** 一次性获取所有的字典类型 */
  async getAll() {
    return this.dictTypeRepository.find();
  }

  /**
   * 获取参数总数
   */
  async countConfigList(): Promise<number> {
    return this.dictTypeRepository.count();
  }

  /**
   * 新增
   */
  async create(dto: DictTypeDto): Promise<void> {
    await this.dictTypeRepository.insert(dto);
  }

  /**
   * 更新
   */
  async update(id: number, dto: Partial<DictTypeDto>): Promise<void> {
    await this.dictTypeRepository.update(id, dto);
  }

  /**
   * 删除
   */
  async delete(id: number): Promise<void> {
    await this.dictTypeRepository.delete(id);
  }

  /**
   * 查询单个
   */
  async findOne(id: number): Promise<DictTypeEntity> {
    return this.dictTypeRepository.findOneBy({ id });
  }

  async isExistKey(name: string): Promise<void | never> {
    const result = await this.dictTypeRepository.findOneBy({ name });
    if (result) throw new BusinessException(ErrorEnum.DICT_NAME_EXISTS);
  }

  async getOneByCode(code: string): Promise<DictTypeEntity> {
    return await this.dictTypeRepository.findOneBy({ code });
  }

  async getByCode(code: string): Promise<Record<string, any>> {
    // 从 DictTypeEntity 中查询对应的数据
    const result = await this.dictTypeRepository.findOneBy({ code });

    if (!result) {
      throw new BusinessException(ErrorEnum.DICT_CODE_NOT_FOUND);
    }

    // 从 dictItemService 中查询所有的字典项
    return await this.dictItemService.getAllByTypeId(result.id);
  }

  async getUserType(): Promise<Array<Partial<DictTypeEntity>>> {
    const userType = ['DISEASES', 'GENDER', 'AGE_GROUP', 'EDUCATION_LEVEL', 'OCCUPATION_CATEGORY'];

    const dictTypes = await this.dictTypeRepository.find({
      where: {
        code: In(userType),
      },
			select: ['id', 'name', 'code'],
    });

    // 遍历根据dictTypeId查找对应的item
    const data = await Promise.all(
      dictTypes.map(async (dictType) => {
        const dictItems = await this.dictItemService.getAllByTypeId(dictType.id);
        return {
          ...dictType,
          items: dictItems,
        };
      })
    );

    return data;
  }

  async bindUser(uid: number, labelIds: number[]): Promise<void> {
    await this.dictItemService.bindUser(uid, labelIds);
  }
}
